/**
 * @author nttdocomo
 */
define(function(require) {
	require("./abstractPanel");
	require("./tool")
	require("./header")
	require("../views/panel/panel");
	aries.klass("aries.panel.Panel", aries.panel.AbstractPanel.extend({
		/**
		 * @cfg {Boolean} collapseFirst
		 * `true` to make sure the collapse/expand toggle button always renders first (to the left of) any other tools in
		 * the panel's title bar, `false` to render it last.
		 */
		collapseFirst : true,
		initComponent : function() {
			var me = this;

			/*if (me.collapsible) {
			 // Save state on these two events.
			 this.addStateEvents(['expand', 'collapse']);
			 }*/
			if (me.unstyled) {
				me.setUI('plain');
			}

			if (me.frame) {
				me.setUI(me.ui + '-framed');
			}

			// Backwards compatibility
			me.bridgeToolbars();

			aries.panel.AbstractPanel.prototype.initComponent.apply(this, arguments);
			me.collapseDirection = me.collapseDirection || me.headerPosition || aries.Component.DIRECTION_TOP;

			// Used to track hidden content elements during collapsed state
			//me.hiddenOnCollapse = new Ext.dom.CompositeElement();
		},

		addTool : function(tools) {
			tools = [].concat(tools);

			var me = this, header = me.header, t, tLen = tools.length, tool;

			for ( t = 0; t < tLen; t++) {
				tool = tools[t];

				me.tools.push(tool);

				if (header) {
					header.addTool(tool);
				}
			}

			me.updateHeader();
		},

		/**
		 * @private
		 * @template
		 * Template method to be implemented in subclasses to add their tools after the collapsible tool.
		 */
		addTools : aries.emptyFn,

		beforeRender : function() {
			var me = this, wasCollapsed;

			aries.panel.AbstractPanel.prototype.beforeRender.apply(this, arguments);

			// Add class-specific header tools.
			// Panel adds collapsible and closable.
			me.initTools();

			// Dock the header/title unless we are configured specifically not to create a header
			if (!(me.preventHeader || (me.header === false))) {
				me.updateHeader();
			}

			// If we are rendering collapsed, we still need to save and modify various configs
			if (me.collapsed) {
				if (me.isPlaceHolderCollapse()) {
					me.hidden = true;

					// This will insert the placeholder Component into the ownerCt's child collection
					// Its getRenderTree call which is calling this will then iterate again and
					// recreate the child items array to include the new Component.
					me.placeholderCollapse();
					wasCollapsed = me.collapsed;

					// Temporarily clear the flag so that the header is rendered with a collapse tool in it.
					// Placeholder collapse panels never really collapse, they just hide. The tool is always
					// a collapse tool.
					me.collapsed = false;
				} else {
					me.beginCollapse();
					me.addClsWithUI(me.collapsedCls);
				}
			}

			// Restore the flag if we are being rendered initially placeholder collapsed.
			if (wasCollapsed) {
				me.collapsed = wasCollapsed;
			}
		},

		bridgeToolbars : function() {
			var me = this, docked = [], fbar, fbarDefaults, minButtonWidth = me.minButtonWidth;

			function initToolbar(toolbar, pos, useButtonAlign) {
				if ($.isArray(toolbar)) {
					toolbar = {
						xtype : 'toolbar',
						items : toolbar
					};
				} else if (!toolbar.xtype) {
					toolbar.xtype = 'toolbar';
				}
				toolbar.dock = pos;
				if (pos == 'left' || pos == 'right') {
					toolbar.vertical = true;
				}

				// Legacy support for buttonAlign (only used by buttons/fbar)
				if (useButtonAlign) {
					toolbar.layout = Ext.applyIf(toolbar.layout || {}, {
						// default to 'end' (right-aligned) if me.buttonAlign is undefined or invalid
						pack : { left:'start', center:'center' }[me.buttonAlign] || 'end'
					});
				}
				return toolbar;
			}

			// Short-hand toolbars (tbar, bbar and fbar plus new lbar and rbar):

			/**
			 * @cfg {String} buttonAlign
			 * The alignment of any buttons added to this panel. Valid values are 'right', 'left' and 'center' (defaults to
			 * 'right' for buttons/fbar, 'left' for other toolbar types).
			 *
			 * **NOTE:** The prefered way to specify toolbars is to use the dockedItems config. Instead of buttonAlign you
			 * would add the layout: { pack: 'start' | 'center' | 'end' } option to the dockedItem config.
			 */

			/**
			 * @cfg {Object/Object[]} tbar
			 * Convenience config. Short for 'Top Bar'.
			 *
			 *     tbar: [
			 *       { xtype: 'button', text: 'Button 1' }
			 *     ]
			 *
			 * is equivalent to
			 *
			 *     dockedItems: [{
			 *         xtype: 'toolbar',
			 *         dock: 'top',
			 *         items: [
			 *             { xtype: 'button', text: 'Button 1' }
			 *         ]
			 *     }]
			 */
			if (me.tbar) {
				docked.push(initToolbar(me.tbar, 'top'));
				me.tbar = null;
			}

			/**
			 * @cfg {Object/Object[]} bbar
			 * Convenience config. Short for 'Bottom Bar'.
			 *
			 *     bbar: [
			 *       { xtype: 'button', text: 'Button 1' }
			 *     ]
			 *
			 * is equivalent to
			 *
			 *     dockedItems: [{
			 *         xtype: 'toolbar',
			 *         dock: 'bottom',
			 *         items: [
			 *             { xtype: 'button', text: 'Button 1' }
			 *         ]
			 *     }]
			 */
			if (me.bbar) {
				docked.push(initToolbar(me.bbar, 'bottom'));
				me.bbar = null;
			}

			/**
			 * @cfg {Object/Object[]} buttons
			 * Convenience config used for adding buttons docked to the bottom of the panel. This is a
			 * synonym for the {@link #fbar} config.
			 *
			 *     buttons: [
			 *       { text: 'Button 1' }
			 *     ]
			 *
			 * is equivalent to
			 *
			 *     dockedItems: [{
			 *         xtype: 'toolbar',
			 *         dock: 'bottom',
			 *         ui: 'footer',
			 *         defaults: {minWidth: {@link #minButtonWidth}},
			 *         items: [
			 *             { xtype: 'component', flex: 1 },
			 *             { xtype: 'button', text: 'Button 1' }
			 *         ]
			 *     }]
			 *
			 * The {@link #minButtonWidth} is used as the default {@link Ext.button.Button#minWidth minWidth} for
			 * each of the buttons in the buttons toolbar.
			 */
			if (me.buttons) {
				me.fbar = me.buttons;
				me.buttons = null;
			}

			/**
			 * @cfg {Object/Object[]} fbar
			 * Convenience config used for adding items to the bottom of the panel. Short for Footer Bar.
			 *
			 *     fbar: [
			 *       { type: 'button', text: 'Button 1' }
			 *     ]
			 *
			 * is equivalent to
			 *
			 *     dockedItems: [{
			 *         xtype: 'toolbar',
			 *         dock: 'bottom',
			 *         ui: 'footer',
			 *         defaults: {minWidth: {@link #minButtonWidth}},
			 *         items: [
			 *             { xtype: 'component', flex: 1 },
			 *             { xtype: 'button', text: 'Button 1' }
			 *         ]
			 *     }]
			 *
			 * The {@link #minButtonWidth} is used as the default {@link Ext.button.Button#minWidth minWidth} for
			 * each of the buttons in the fbar.
			 */
			if (me.fbar) {
				fbar = initToolbar(me.fbar, 'bottom', true);
				// only we useButtonAlign
				fbar.ui = 'footer';

				// Apply the minButtonWidth config to buttons in the toolbar
				if (minButtonWidth) {
					fbarDefaults = fbar.defaults;
					fbar.defaults = function(config) {
						var defaults = fbarDefaults || {};
						if ((!config.xtype || config.xtype === 'button' || (config.isComponent && config.isXType('button'))) && !('minWidth' in defaults)) {
							defaults = Ext.apply({
								minWidth : minButtonWidth
							}, defaults);
						}
						return defaults;
					};
				}

				docked.push(fbar);
				me.fbar = null;
			}

			/**
			 * @cfg {Object/Object[]} lbar
			 * Convenience config. Short for 'Left Bar' (left-docked, vertical toolbar).
			 *
			 *     lbar: [
			 *       { xtype: 'button', text: 'Button 1' }
			 *     ]
			 *
			 * is equivalent to
			 *
			 *     dockedItems: [{
			 *         xtype: 'toolbar',
			 *         dock: 'left',
			 *         items: [
			 *             { xtype: 'button', text: 'Button 1' }
			 *         ]
			 *     }]
			 */
			if (me.lbar) {
				docked.push(initToolbar(me.lbar, 'left'));
				me.lbar = null;
			}

			/**
			 * @cfg {Object/Object[]} rbar
			 * Convenience config. Short for 'Right Bar' (right-docked, vertical toolbar).
			 *
			 *     rbar: [
			 *       { xtype: 'button', text: 'Button 1' }
			 *     ]
			 *
			 * is equivalent to
			 *
			 *     dockedItems: [{
			 *         xtype: 'toolbar',
			 *         dock: 'right',
			 *         items: [
			 *             { xtype: 'button', text: 'Button 1' }
			 *         ]
			 *     }]
			 */
			if (me.rbar) {
				docked.push(initToolbar(me.rbar, 'right'));
				me.rbar = null;
			}

			if (me.dockedItems) {
				if (!$.isArray(me.dockedItems)) {
					me.dockedItems = [me.dockedItems];
				}
				me.dockedItems = me.dockedItems.concat(docked);
			} else {
				me.dockedItems = docked;
			}
		},

		/**
		 * @private
		 * Tools are a Panel-specific capabilty.
		 * Panel uses initTools. Subclasses may contribute tools by implementing addTools.
		 */
		initTools : function() {
			var me = this;

			me.tools = me.tools ? _.clone(me.tools) : [];

			// Add a collapse tool unless configured to not show a collapse tool
			// or to not even show a header.
			if (me.collapsible && !(me.hideCollapseTool || me.header === false || me.preventHeader)) {
				me.collapseDirection = me.collapseDirection || me.headerPosition || 'top';
				me.collapseTool = me.expandTool = new aries.panel.Tool({
					xtype : aries.panel.Tool,
					type : (me.collapsed && !me.isPlaceHolderCollapse()) ? ('expand-' + me.getOppositeDirection(me.collapseDirection)) : ('collapse-' + me.collapseDirection),
					handler : me.toggleCollapse,
					scope : me
				})/*Ext.widget({
				xtype : 'tool',
				type : (me.collapsed && !me.isPlaceHolderCollapse()) ? ('expand-' + me.getOppositeDirection(me.collapseDirection)) : ('collapse-' + me.collapseDirection),
				handler : me.toggleCollapse,
				scope : me
				});*/

				// Prepend collapse tool is configured to do so.
				if (me.collapseFirst) {
					me.tools.unshift(me.collapseTool);
				}
			}

			// Add subclass-specific tools.
			me.addTools();

			// Make Panel closable.
			if (me.closable) {
				me.addClsWithUI('closable');
				me.addTool({
					type : 'close',
					handler : Ext.Function.bind(me.close, me, [])
				});
			}

			// Append collapse tool if needed.
			if (me.collapseTool && !me.collapseFirst) {
				me.addTool(me.collapseTool);
			}
		},

		initHeaderAria : function() {
			var me = this, el = me.$el, header = me.header;
			/*if (el && header) {
			 el.attr('aria-labelledby', header.titleCmp.id);
			 }*/
		},

		/**
		 * Create, hide, or show the header component as appropriate based on the current config.
		 * @private
		 * @param {Boolean} force True to force the header to be created
		 */
		updateHeader : function(force) {
			var me = this, header = me.header, title = me.title, tools = me.tools, vertical = me.headerPosition == 'left' || me.headerPosition == 'right';

			if ((header !== false) && (force || title || (tools && tools.length) || (me.collapsible && !me.titleCollapse))) {
				if (header && header.isHeader) {
					header.show();
				} else {

					// Apply the header property to the header config
					header = me.header = new aries.panel.Header(_.extend({
						xtype : aries.panel.Header,
						title : title,
						titleAlign : me.titleAlign,
						orientation : vertical ? 'vertical' : 'horizontal',
						dock : me.headerPosition || 'top',
						textCls : me.headerTextCls,
						iconCls : me.iconCls,
						icon : me.icon,
						baseCls : me.baseCls + '-header',
						tools : tools,
						ui : me.ui,
						id : me.id + '_header',
						indicateDrag : me.draggable,
						frame : me.frame && me.frameHeader,
						ignoreParentFrame : me.frame || me.overlapHeader,
						ignoreBorderManagement : me.frame || me.ignoreHeaderBorderManagement,
						listeners : me.collapsible && me.titleCollapse ? {
							click : me.toggleCollapse,
							scope : me
						} : null
					}, me.header))/*Ext.widget(Ext.apply({
					 xtype : 'header',
					 title : title,
					 titleAlign : me.titleAlign,
					 orientation : vertical ? 'vertical' : 'horizontal',
					 dock : me.headerPosition || 'top',
					 textCls : me.headerTextCls,
					 iconCls : me.iconCls,
					 icon : me.icon,
					 baseCls : me.baseCls + '-header',
					 tools : tools,
					 ui : me.ui,
					 id : me.id + '_header',
					 indicateDrag : me.draggable,
					 frame : me.frame && me.frameHeader,
					 ignoreParentFrame : me.frame || me.overlapHeader,
					 ignoreBorderManagement : me.frame || me.ignoreHeaderBorderManagement,
					 listeners : me.collapsible && me.titleCollapse ? {
					 click : me.toggleCollapse,
					 scope : me
					 } : null
					 }, me.header));*/
					me.addDocked(header, 0);
					//header.renderEl()

					// Reference the Header's tool array.
					// Header injects named references.
					me.tools = header.tools;
				}
				me.initHeaderAria();
			} else if (header) {
				header.hide();
			}
		}
	}, {
		xtype : "panel"
	}))
})
